from xml.dom import minidom
import misc
from wavefront import ObjModel
from scene import create_picture, create_ground, create_skybox
import euclid
import context
import groups
import world

class CamSettings:
    def __init__(self, position=None, direction=None, up=None):
        self.position = position
        self.direction = direction
        self.up_axis = up

def getAttributs(node):
    attributs = node.attributes
    res = {}
    for cle in attributs.keys():
        attr = attributs[cle]
        res[cle] = attr.value
    return res 

def load_scene(attr, parent_transform):
    context._context.cam_settings = CamSettings(misc.getVal(attr, misc.tuple_f, "look", (10.0 ,1.6, 0.0)),
                                                misc.getVal(attr, float, "dir", 0.0),
                                                misc.getVal(attr, misc.tuple_f, "up", (0.0, 1.0, 0.0)))
    return parent_transform
    

def load_skybox(attr, parent_transform):
    valeurTexture = misc.getVal(attr, str, "texture", misc.data_path("skyboxes/miramar_large.jpg"))
    valeurSize = misc.getVal(attr, float,"size", 500)
    create_skybox(parent_transform, valeurTexture, valeurSize)
    return parent_transform

def load_obj(attr, parent_transform):
    valeurUrl = misc.getVal(attr,str,"url", misc.data_path("obj/porte1.obj"))
    obj = ObjModel()
    obj.load(groups.pack_transform(parent_transform), valeurUrl)
    return parent_transform

def load_transform(attr, parent_transform):
    trans = misc.getVal(attr, misc.tuple_f, "translation", (0.0, 0.0, 0.0))
    rot_x, rot_y, rot_z = misc.getVal(attr, misc.tuple_f, "rotation", (0.0, 0.0, 0.0))
    scale = misc.getVal(attr, misc.tuple_f, "echelle", (1.0, 1.0, 1.0))
    
    if trans != (0.0, 0.0, 0.0):
        parent_transform = parent_transform * euclid.Matrix4.new_translate(*trans)

    if rot_x != 0.0:
        parent_transform = parent_transform * euclid.Matrix4.new_rotatex(rot_x)

    if rot_y != 0.0:
        parent_transform = parent_transform * euclid.Matrix4.new_rotatey(rot_y)

    if rot_z != 0.0:
        parent_transform = parent_transform * euclid.Matrix4.new_rotatez(rot_z)
    
    if scale != (1.0, 1.0, 1.0):
        parent_transform = parent_transform * euclid.Matrix4.new_scale(scale)
    
    return parent_transform

def load_display_list(attr, parent_transform):
    return parent_transform

def load_picture(attr, parent_transform):
    valeurTexture = misc.getVal(attr, str, "texture", misc.data_path("skyboxes/miramar_large.jpg"))
    valeurHauteur = misc.getVal(attr, float, "hauteur", 1.0)
    valeurLargeur = misc.getVal(attr, float, "largeur", 1.0)
    create_picture(parent_transform, valeurLargeur, valeurHauteur, valeurTexture)
    
    return parent_transform

def load_ground(attr, parent_transform):
    valeurTaille = misc.getVal(attr, float, "taille", world.block_size)
    valeurTexture = misc.getVal(attr, str, "texture", "textures/sol.png")
    
    create_ground(parent_transform, valeurTaille, valeurTexture)
    return parent_transform


_loaders = {"Scene" : load_scene, "SkyBox" : load_skybox, "Obj" : load_obj,
            "Transform" : load_transform, "DisplayList" : load_display_list,
            "Tableau" : load_picture, "Sol" : load_ground}

def parse(node, parent_transform):
    """
    parentGroup for transform elements is set in load_transform function
    """
    
    node_type = node.tagName
    attrs = getAttributs(node)
    
    parent_transform = _loaders[node_type](attrs, parent_transform)
    
    for e in node.childNodes:
        if e.nodeType == e.ELEMENT_NODE:
            parse(e, parent_transform)
    
    print "==============================================================="
    print "Node : ", node_type
    print "Attr : ", attrs
    print "==============================================================="


def parser(nomFichier):
    fichier = open(nomFichier)
    xmldoc = minidom.parse(fichier)
    fichier.close()
    
    return parse(xmldoc.childNodes[0], euclid.Matrix4())	


